<!--
  智慧小区管理系统 - 数据表格组件
  @author Wu.Liang
  @date 2024-01-01
-->
<template>
    <div class="data-table">
        <!-- 表格工具栏 -->
        <div class="table-toolbar" v-if="showToolbar">
            <div class="toolbar-left">
                <slot name="toolbar-left">
                    <el-button type="primary" :icon="Plus" @click="handleAdd" v-if="showAdd">
                        新增
                    </el-button>
                    <el-button :icon="Download" @click="handleExport" v-if="showExport">
                        导出
                    </el-button>
                </slot>
            </div>
            <div class="toolbar-right">
                <slot name="toolbar-right">
                    <el-input v-model="searchKeyword" placeholder="请输入关键词搜索" :prefix-icon="Search" clearable
                        style="width: 240px" @input="handleSearch" v-if="showSearch" />
                    <el-button :icon="Refresh" @click="handleRefresh" v-if="showRefresh">
                        刷新
                    </el-button>
                </slot>
            </div>
        </div>

        <!-- 表格内容 -->
        <el-table ref="tableRef" :data="tableData" :loading="loading" :border="border" :stripe="stripe" :size="size"
            :height="height" :max-height="maxHeight" @selection-change="handleSelectionChange"
            @sort-change="handleSortChange" v-bind="$attrs">
            <!-- 多选列 -->
            <el-table-column type="selection" width="50" v-if="showSelection" />

            <!-- 序号列 -->
            <el-table-column type="index" label="序号" width="60" v-if="showIndex" :index="getIndex" />

            <!-- 数据列 -->
            <slot />

            <!-- 操作列 -->
            <el-table-column label="操作" :width="actionWidth" fixed="right" v-if="showAction">
                <template #default="scope">
                    <slot name="action" :row="scope.row" :index="scope.$index">
                        <el-button type="primary" link :icon="Edit" @click="handleEdit(scope.row)" v-if="showEdit">
                            编辑
                        </el-button>
                        <el-button type="danger" link :icon="Delete" @click="handleDelete(scope.row)" v-if="showDelete">
                            删除
                        </el-button>
                    </slot>
                </template>
            </el-table-column>
        </el-table>

        <!-- 分页组件 -->
        <div class="table-pagination" v-if="showPagination">
            <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :total="total"
                :page-sizes="pageSizes" :background="true" layout="total, sizes, prev, pager, next, jumper"
                @size-change="handleSizeChange" @current-change="handleCurrentChange" />
        </div>
    </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue'
import { ElMessageBox } from 'element-plus'
import {
    Plus,
    Download,
    Search,
    Refresh,
    Edit,
    Delete
} from '@element-plus/icons-vue'

// Props定义
interface Props {
    data?: any[]
    loading?: boolean
    total?: number
    currentPage?: number
    pageSize?: number
    pageSizes?: number[]
    showToolbar?: boolean
    showAdd?: boolean
    showExport?: boolean
    showSearch?: boolean
    showRefresh?: boolean
    showSelection?: boolean
    showIndex?: boolean
    showAction?: boolean
    showEdit?: boolean
    showDelete?: boolean
    showPagination?: boolean
    actionWidth?: number
    border?: boolean
    stripe?: boolean
    size?: 'large' | 'default' | 'small'
    height?: string | number
    maxHeight?: string | number
}

const props = withDefaults(defineProps<Props>(), {
    data: () => [],
    loading: false,
    total: 0,
    currentPage: 1,
    pageSize: 10,
    pageSizes: () => [10, 20, 50, 100],
    showToolbar: true,
    showAdd: true,
    showExport: true,
    showSearch: true,
    showRefresh: true,
    showSelection: false,
    showIndex: true,
    showAction: true,
    showEdit: true,
    showDelete: true,
    showPagination: true,
    actionWidth: 150,
    border: true,
    stripe: true,
    size: 'default'
})

// Emits定义
const emit = defineEmits<{
    add: []
    edit: [row: any]
    delete: [row: any]
    export: []
    search: [keyword: string]
    refresh: []
    'selection-change': [selection: any[]]
    'sort-change': [sort: any]
    'size-change': [size: number]
    'current-change': [page: number]
}>()

// 响应式数据
const tableRef = ref()
const searchKeyword = ref('')
const tableData = computed(() => props.data)
const currentPage = ref(props.currentPage)
const pageSize = ref(props.pageSize)

// 监听props变化
watch(
    () => props.currentPage,
    (val) => {
        currentPage.value = val
    }
)

watch(
    () => props.pageSize,
    (val) => {
        pageSize.value = val
    }
)

// 获取序号
const getIndex = (index: number) => {
    return (currentPage.value - 1) * pageSize.value + index + 1
}

// 处理新增
const handleAdd = () => {
    emit('add')
}

// 处理编辑
const handleEdit = (row: any) => {
    emit('edit', row)
}

// 处理删除
const handleDelete = async(row: any) => {
    try {
        await ElMessageBox.confirm('确定要删除这条数据吗？', '提示', {
            confirmButtonText: '确定',
            cancelButtonText: '取消',
            type: 'warning'
        })
        emit('delete', row)
    } catch {
        // 用户取消删除
    }
}

// 处理导出
const handleExport = () => {
    emit('export')
}

// 处理搜索
const handleSearch = () => {
    emit('search', searchKeyword.value)
}

// 处理刷新
const handleRefresh = () => {
    emit('refresh')
}

// 处理选择变化
const handleSelectionChange = (selection: any[]) => {
    emit('selection-change', selection)
}

// 处理排序变化
const handleSortChange = (sort: any) => {
    emit('sort-change', sort)
}

// 处理页大小变化
const handleSizeChange = (size: number) => {
    pageSize.value = size
    emit('size-change', size)
}

// 处理页码变化
const handleCurrentChange = (page: number) => {
    currentPage.value = page
    emit('current-change', page)
}

// 暴露方法
const clearSelection = () => {
    tableRef.value?.clearSelection()
}

const toggleRowSelection = (row: any, selected?: boolean) => {
    tableRef.value?.toggleRowSelection(row, selected)
}

const toggleAllSelection = () => {
    tableRef.value?.toggleAllSelection()
}

defineExpose({
    clearSelection,
    toggleRowSelection,
    toggleAllSelection
})
</script>

<style scoped lang="scss">
.data-table {
    .table-toolbar {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 16px;
        padding: 0 4px;

        .toolbar-left {
            display: flex;
            gap: 8px;
        }

        .toolbar-right {
            display: flex;
            gap: 8px;
            align-items: center;
        }
    }

    .table-pagination {
        display: flex;
        justify-content: flex-end;
        margin-top: 16px;
        padding: 0 4px;
    }
}

@media (max-width: 768px) {
    .data-table {
        .table-toolbar {
            flex-direction: column;
            gap: 12px;

            .toolbar-left,
            .toolbar-right {
                width: 100%;
                justify-content: space-between;
            }
        }

        .table-pagination {
            justify-content: center;
        }
    }
}
</style>
